#include "ReflectProcess.h"
#include "Utils/LogUtil.h"
#include "Render/RenderState.h"
#include "Core/CoreGlobals.h"
#include "Game/Scene/Entity.h"
#include "Game/Component/Model.h"
#include "Render/Buffer/VertexBuffer.h"
#include "Render/Buffer/IndexBuffer.h"
#include "Render/Buffer/CustomBuffer.h"

void ReflectProcess::OnInit()
{

	ENQUEUE_RENDER_COMMAND(BuildModel)([this](VkCommandBuffer commandBuffer)
		{

			GeometryGenerator geometryGenerator;
			GeometryGenerator::MeshData sphereData = geometryGenerator.CreateSphere(2.f, 20, 20);

			std::vector<VertexPosNormal> tempVertexs;
			tempVertexs.resize(sphereData.Vertices.size());
			for (uint32 i = 0; i < sphereData.Vertices.size(); ++i)
			{
				tempVertexs[i].pos = sphereData.Vertices[i].Position;
				tempVertexs[i].normal = sphereData.Vertices[i].Normal;
			}

			mVertexBuffer = mVertexBuffer = VertexBuffer::Builder()
				.SetData(tempVertexs.data())
				.SetSize(tempVertexs.size() * sizeof(VertexPosNormal))
				.Build();

			mIndexBuffer = IndexBuffer::Builder()
				.SetData(sphereData.Indices32.data())
				.SetSize(sphereData.Indices32.size() * sizeof(uint32))
				.SetIndexCount(sphereData.Indices32.size())
				.Build();

			RefCountPtr<RHIBuffer> uboBuffer = GetBuffer(PREV_PROCESS, "UboBuffer");
			RefCountPtr<RHIBuffer> exposureBuffer = GetBuffer(PREV_PROCESS, "ExposureBuffer");
			RefCountPtr<RHITexture> hdrTexture = GetTexture(PREV_PROCESS, "HdrTexture");
			RefCountPtr<RHISampler> hdrSampler = GetSampler(PREV_PROCESS, "HdrSampler");

			RHIDescriptor::Builder descriptorBuilder;
			mHdrVertexShader = descriptorBuilder.AddShader<HdrVertexShader>();
			mHdrFragmentShader = descriptorBuilder.AddShader<HdrFragmentShader>();

			mHdrVertexShader->type->SetVaule(1);
			mHdrFragmentShader->type->SetVaule(1);

			mDescriptor = descriptorBuilder
				.SetDescriptorCount(0, 1)
				.Build();

			mDescriptor->SetValue("ubo", uboBuffer);
			mDescriptor->SetValue("samplerEnvMap", hdrTexture, hdrSampler);
			mDescriptor->SetValue("exposure", exposureBuffer);
			mDescriptorMask = mDescriptor->AllocateDescriptor();

			RefCountPtr<ColorRenderTarget> colorRenderTarget0 = GetTexture(PREV_PROCESS, "ColorRenderTarget0");
			RefCountPtr<ColorRenderTarget> colorRenderTarget1 = GetTexture(PREV_PROCESS, "ColorRenderTarget1");
			RefCountPtr<DepthRenderTarget> depthRenderTarget = GetTexture(PREV_PROCESS, "DepthRenderTarget");
			RefCountPtr<RHIRenderPass> renderPass = GetRenderPass(PREV_PROCESS, "RenderPass");

			mPipeline = GraphicsPipeline::Builder()
				.SetDescriptor(mDescriptor)
				.AddColorRenderTarget(colorRenderTarget0)
				.AddColorRenderTarget(colorRenderTarget1)
				.SetDepthRenderTarget(depthRenderTarget)
				.SetDstStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
				.SetDstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
				.SetSrcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
				.SetSrcAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
				.SetRenderPass(renderPass->GetRenderPass())
				.Build();
		});
}

void ReflectProcess::OnTick(float deltaTime)
{
	ENQUEUE_RENDER_COMMAND(RecordCommand)([this](VkCommandBuffer commandBuffer)
		{
			vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mPipeline->GetPipeline());

			vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mPipeline->GetPipelineLayout(), 0, 1, &mDescriptorMask.GetDescriptorSet(), 0, nullptr);

			VkBuffer vertexBuffer = mVertexBuffer->GetBuffer();
			VkDeviceSize offsets = 0;
			vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer, &offsets);

			VkBuffer indexBuffer = mIndexBuffer->GetBuffer();
			vkCmdBindIndexBuffer(commandBuffer, indexBuffer, 0, VK_INDEX_TYPE_UINT32);

			vkCmdDrawIndexed(commandBuffer, mIndexBuffer->GetIndexCount(), 1, 0, 0, 0);

			vkCmdEndRenderPass(commandBuffer);
		});
}

void ReflectProcess::OnResize()
{
}
